ASIC implementation
Table of content
1. Introduction
This section covers specific points of the openMSP430 ASIC
implementation, in particular:
- The ASIC specific RTL configuration options.
- Some DFT
considerations.
- A description of each ASIC sensitive module.
Keep in mind that as no exotic design technique were used in the
openMSP430,
following a standard implementation flow from
Synthesis to P&R is the best way to go.
2. RTL Configuration
Whenever the "
`define
ASIC" statement of the
Expert
System Configuration section is uncommented, all ASIC specific
configuration options are enabled.
2.1 Basic Clock Module
In its ASIC configuration, the Basic clock module of the openMSP430 can
support
up to all features
described
in the MSP430x1xx Family User's
Guide (Chapter 4).
In particular, the
ASIC_CLOCKING
option activates all advancd clocking options (note that formal equivalence with
the FPGA version is achieved by commenting this option out):
|
|
|
//===============================================================
// ASIC CLOCKING
//===============================================================
//-------------------------------------------------------
// When uncommented, this define will enable the ASIC
// architectural clock gating as well as the advanced low
// power modes support (most common).
// Comment this out in order to get FPGA-like clocking.
//-------------------------------------------------------
`define ASIC_CLOCKING
|
All these advanced clocking options are highlighted in the following diagram and
discussed below:
2.1.1 Low-Frequency Clock Domain
The LFXT clock domain can be enabled thanks to the following
configuration
option:
|
|
|
//============================================================================
// LFXT CLOCK DOMAIN
//============================================================================
//-------------------------------------------------------
// When uncommented, this define will enable the lfxt_clk
// clock domain.
// When commented out, the whole chip is clocked with dco_clk.
//-------------------------------------------------------
`define LFXT_DOMAIN
|
Note
1: When commented-out:
- ACLK is running on DCO_CLK
- MCLK_MUX and SMCLK_MUX options are not supported
- OSCOFF_EN low power mode is not supported
Note
2: Unlike its name suggest, there is no frequency limitation on
LFXT_CLK. The name was simply kept
in order to be consistent with the original MSP430 documentation, where
LFXT_CLK is
typically connected to a 32 kHz crystal oscillator.
2.1.2 Clock Muxes
The
MCLK and
SMCLK clock muxes can be enabled or
disabled with the following options:
|
|
|
//============================================================================
// CLOCK MUXES
//============================================================================
//-------------------------------------------------------
// MCLK: Clock Mux
//-------------------------------------------------------
// When uncommented, this define will enable the
// MCLK clock MUX allowing the selection between
// DCO_CLK and LFXT_CLK with the BCSCTL2.SELMx register.
// When commented, DCO_CLK is selected.
//-------------------------------------------------------
`define MCLK_MUX
//-------------------------------------------------------
// SMCLK: Clock Mux
//-------------------------------------------------------
// When uncommented, this define will enable the
// SMCLK clock MUX allowing the selection between
// DCO_CLK and LFXT_CLK with the BCSCTL2.SELS register.
// When commented, DCO_CLK is selected.
//-------------------------------------------------------
`define SMCLK_MUX
|
Note
1: When a MUX is excluded, the concerned clock (
MCLK and/or
SMCLK) is running with
DCO_CLK.
Note
2: If a MUX is included, the implementation and sign-off tools
(in particular CTS and STA) must be aware
that a new clock needs to be defined on the MUX output.
2.1.3 Clock Dividers
The
MCLK,
SMCLK and ACLK clock dividers can
be enabled or disabled with the following options:
|
|
|
//============================================================================
// CLOCK DIVIDERS
//============================================================================
//-------------------------------------------------------
// MCLK: Clock divider
//-------------------------------------------------------
// When uncommented, this define will enable the
// MCLK clock divider (/1/2/4/8)
//-------------------------------------------------------
`define MCLK_DIVIDER
//-------------------------------------------------------
// SMCLK: Clock divider (/1/2/4/8)
//-------------------------------------------------------
// When uncommented, this define will enable the
// SMCLK clock divider
//-------------------------------------------------------
`define SMCLK_DIVIDER
//-------------------------------------------------------
// ACLK: Clock divider (/1/2/4/8)
//-------------------------------------------------------
// When uncommented, this define will enable the
// ACLK clock divider
//-------------------------------------------------------
`define ACLK_DIVIDER
|
The clock dividers instantiate a clock gate on the clock tree and are
implemented as following:
2.1.4 Low-Power Modes
2.1.4.1 Internal clocks ( MCLK /
SMCLK )
Two bit fields in the status register (R2) allow to
control the system clocks:
- CPUOFF allows to
switch-off MCLK
- SCG1 allows to
switch-off SMCLK
These control bits are supported by the openMSP430 and can be
included in the design with the following defines:
|
|
|
//============================================================================
// LOW POWER MODES
//============================================================================
//-------------------------------------------------------
// LOW POWER MODE: CPUOFF
//-------------------------------------------------------
// When uncommented, this define will include the
// clock gate allowing to switch off MCLK in
// all low power modes: LPM0, LPM1, LPM2, LPM3, LPM4
//-------------------------------------------------------
`define CPUOFF_EN
//-------------------------------------------------------
// LOW POWER MODE: SCG1
//-------------------------------------------------------
// When uncommented, this define will include the
// clock gate allowing to switch off SMCLK in
// the following low power modes: LPM2, LPM3, LPM4
//-------------------------------------------------------
`define SCG1_EN
|
In order to keep the clock tree as flat as possible, the CPUOFF and
SCG1 low power options share the same clock gate with the clock divider:
2.1.4.2 Clock oscillators (
DCO_CLK / LFXT_CLK )
There are two bit fields in the status register (R2) allowing to
control the clock oscillators:
- SCG0 allows to
switch-off the DCO oscillator
- OSCOFF allows to
switch-off the LFXT oscillator
These control bits are supported by the openMSP430 and can be
included in the design with the following defines:
|
|
|
//============================================================================
// LOW POWER MODES
//============================================================================
//-------------------------------------------------------
// LOW POWER MODE: SCG0
//-------------------------------------------------------
// When uncommented, this define will enable the
// DCO_ENABLE/WKUP port control (always 1 when commented).
// This allows to switch off the DCO oscillator in the
// following low power modes: LPM1, LPM3, LPM4
//-------------------------------------------------------
`define SCG0_EN
//-------------------------------------------------------
// LOW POWER MODE: OSCOFF
//-------------------------------------------------------
// When uncommented, this define will include the
// LFXT_CLK clock gate and enable the LFXT_ENABLE/WKUP
// port control (always 1 when commented).
// This allows to switch off the low frequency oscillator
// in the following low power modes: LPM4
//-------------------------------------------------------
`define OSCOFF_EN
|
The control logic of both DCO and LFXT oscillators is identical.
When disabled, the
*_WKUP
signal
is used to asynchronously wake up the oscillator. Once the oscillator
is awake (and therefore a clock is available), the
*_ENABLE signal will take over and
synchronously keep the oscillator enabled until the CPU clears the SCG0
or OSCOFF bit again.
The following two waveforms illustrate the CPU entering the LPM1 mode,
and in particular the DCO oscillator being switched-off:
- Entering LPM1 through a BIS
#N, R2
instruction:
- Entering LPM1 through a RETI
instruction:
Note:
the DCO oscillator is enabled until the BIS and RETI instruction are
fully executed (i.e. until the CPU state machines reach their IDLE
state).
At last, this waveform shows the CPU going out of LPM1 mode and in
particular the DCO oscillator wake-up sequence:
In order to wake-up the CPU from ANY low power mode, the system
MUST ALWAYS go through the following
chain of events (as illustrated in the previous waveform):
- The
peripheral (for example a timer) asserts the WKUP input of the openMSP430 in order to
asynchronously restore the clocks. At this stage, DCO_WKUP is activated and DCO_ENABLE is still cleared.
- Once
MCLK is available, the peripheral generates a synchronous IRQ signal in
order to re-activate the CPU state machines.
- The CPU
state machines activated, DCO_ENABLE is synchronously set.
- When
the global interrupt enable flag (GIE) is cleared, DCO_WKUP is
released two clock cycles later (i.e. same behavior as a reset
synchronizer).
Important
note: the peripheral should release the WKUP input when its interrupt pending flag is cleared. Otherwise the DCO_WKUP signal
will be set again as soon as the GIE flag is restored by the RETI
instruction... which is probably not the intended behavior :-P
- The DCO
oscillator is now enabled until SCG0 is set again.
2.2 Other configuration options
2.2.1 Fine Grained Clock Gating
Nowadays, all synthesis tools support automatic (fine grained) clock
gating insertion.
However, as some design houses still prefer to have the clock gates
directly instantiated in the RTL, there is the possibility to include
the
'manual' fine grained
clock gates in the design with the following define:
|
|
|
//============================================================================
// FINE GRAINED CLOCK GATING
//============================================================================
//-------------------------------------------------------
// When uncommented, this define will enable the fine
// grained clock gating of all registers in the core.
//-------------------------------------------------------
`define CLOCK_GATING
|
2.2.2 Watchdog Clock Mux
The
watchdog clock mux allows to select between ACLK and SMCLK. It can be enabled or
disabled with the WATCHDOG_MUX
define.
When excluded, the additional
WATCHDOG_NOMUX_ACLK
option allows the user to decide if the watchdog clock should be
hard-wired to
ACLK (if
uncommented) or
SMCLK (if
commented-out)
|
|
|
//============================================================================
// CLOCK MUXES
//============================================================================
//-------------------------------------------------------
// WATCHDOG: Clock Mux
//-------------------------------------------------------
// When uncommented, this define will enable the
// Watchdog clock MUX allowing the selection between
// ACLK and SMCLK with the WDTCTL.WDTSSEL register.
// When commented out, ACLK is selected if the
// WATCHDOG_NOMUX_ACLK define is uncommented, SMCLK is
// selected otherwise.
//-------------------------------------------------------
`define WATCHDOG_MUX
//`define WATCHDOG_NOMUX_ACLK
|
3. DFT Considerations
The openMSP430 is designed to be fully scan friendly. During
production, the ATE controls the core through the
scan_mode and
scan_enable
signals. The
scan_mode
port is always asserted during scan testing and is used to switch
between functional and scan mode.
3.1 Resets
When in scan mode (i.e.
scan_mode input
port is set),
ALL internal
resets of the openMSP430 are connected the
reset_n input
port.
Taking the
POR
generation as an example, it is implemented using the
omsp_scan_mux module as following:
3.2 Clock Gates
When in scan mode (i.e.
scan_mode input
port is set),
ALL clock gates
instantiated in the design must
be
enabled during scan shifting.
This is can be achieved by setting the
scan_enable
input port during the shift phase.
On the other hand, during the capture phase, the
scan_enable port
must be cleared in order to restore the functional behavior of the
clock gate.
This feature is implemented in the
omsp_clock_gate
module as following:
3.3 Clock Muxes
When in scan mode (i.e.
scan_mode input
port is set), the
MCLK
and
SMCLK
clock muxes are both running on
DCO_CLK. The
watchdog mux is running
SMCLK (i.e.
DCO_CLK).
This feature is implemented in the
omsp_clock_mux
module as following:
Note:
if the LFXT clock domain is enabled, the
LFXT_CLK input
port should also be connected to the scan clock when in scan mode.
3.4 Coverage
After synthesizing the openMSP430 in its maximum configuration (in
particular with ALL clock domains available and ALL clock muxes
included), the core reaches
99.7%
stuck-at fault coverage:
4. Sensitive Modules
ALL modules discussed in this section have
a simple and well defined functionality but nonetheless lay on
sensitive parts of the design (clock tree, wake-up path, ...).
In the industry, it is common place for companies to have policies
recommending designers to use textbook structures or specific
standard cells when implementing circuits considered as 'sensitive'.
This section will hopefully help to quickly identify these
'sensitive' circuits and adapt them to your requirements if necessary.
4.1 AND Gate ( omsp_and_gate.v
)
This module implements a simple AND2 gate and is instantiated several
times on the wake-up paths in order to ensure a glitch free generation
of the wake-up signals. The idea behind this block is to prevent the
synthesis tool from optimizing the combinatorial wake-up path and
potentially
generate a glitchy logic.
There are three different ways to handle this block:
- Do nothing
- Modify the RTL by directly instantiating an AND2 cell from the
target library and applying a don't touch or size only
attribute on it before proceeding to the synthesis compile step
- Keep
the RTL unchanged and when running synthesis, first compile this module
separately before going to the top down compile (don't forget the don't touch or size only
attribute)
Note that the first option is actually acceptable because in low power
mode,
there are no clocks available, which means no glitch... However, in
active mode, the wake-up line could see a lot of glitches, which is
functionally not a problem (since the core is awake anyway) but could
be
considered as not really elegant...
4.2 Clock Gate ( omsp_clock_gate.v
)
Almost every company has a different policy
for handling clock gates. Therefore, this module is probably the most
likely to be modified.
So here are the facts:
- There
are only rising edge flip-flop in the design1
→ as a consequence
clock gates can indifferently park the clock high or low without
affecting functionality.
- The enable signal of ALL clock gates in the openMSP430 are
generated with the rising edge of the clock
→ this leaves the
door open for both LATCH and NAND2 based clock gates.
1: beside for the
DCO_ENABLE
and LFXT_ENABLE signals and the clock MUXes. However, these can be
safely ignored
As a consequence, you can feel free to use:
- A LATCH based clock gate. For example:
- Or a NAND2 based clock gate:
4.3 Clock Mux ( omsp_clock_mux.v
)
The clock muxes of the openMSP430 are implemented as following:
In
order to make this implementation 100% bullet proof, the RTL
could be modified by manually instantiating the NAND2 and AND2
cells directly from the target library (with the associated
don't touch or
size only
attributes of course).
However, if you decide to compile this module as it is, the synthesis
tool should normally be smart enough and not mess it up (but PLEASE
PLEASE PLEASE double check manually the resulting
gate netlist).
4.4 Scan Mux ( omsp_scan_mux.v
)
As illustrated in the section
3.1 , the scan mux cell
allows
ALL internal resets to
be controllable with the
reset_n input
port in scan mode.
In addition, the scan mux is also used by the
omsp_wakeup_cell (see section
4.7 below).
4.5 Sync Cell ( omsp_sync_cell.v
)
The following synchronization cell is instantiated on all clock domain
crossing data paths:
4.6 Sync Reset ( omsp_sync_reset.v
)
Internal resets are generated using the following standard reset
synchronizer:
4.7 Wakeup Cell ( omsp_wakeup_cell.v
)
The wakeup cell is the most unconventional module of the
openMSP430 design as it contains a flip-flop whose clock and reset are
both coming from a data path.
In the openMSP430 core, it is instantiated a single time in the
watchdog
timer but can also be reused in external custom peripherals.
The implementation of the block looks as following:
The basic idea here is simply to set the WKUP_OUT signal with a
rising edge on the WKUP_EVENT port, and clear it when WKUP_CLEAR is
active (i.e. level sensitive clear).
In order to give a better perspective from a system point of view, the
following diagram shows how the wakeup cell has been used in the
particular case of the watchdog timer (note that WDTIFG_CLR_REG and
WDTQN_EDGE_REG are both output of a flip-flop and therefore
glitch-free):
Note:
Wake-up signals can of course be generated in a
different way as long as they directly come from a flip-flop (or are
certified to be non-glitchy).
For example a simple handshake between the WDT_CLK and MCLK clock
domains could have been used to clear the WDT_WKUP signal in a fully
synchronous
manner.
However, it is to be noted that this handshake would introduce some
synchronization
delay, which might not be negligible if MCLK and WDT_CLK frequencies
are orders of magnitude apart (i.e. several MHz for MCLK and 32kHz
for WDT_CLK).
As getting the oscillators back to sleep as fast as possible might
prove to be extremely important for low-power designs, this
asynchronous solution was selected for the
omsp_watchdog
implementation.